#pragma once
#include "socket.hpp"
#include "calculator.hpp"
#include <functional>
#include <signal.h>

using func_t = function<string(string &)>;

class tcp_server {
    static const size_t default_buffer_size = 128;
public:
    tcp_server(uint16_t port, func_t callback) :_port(port), _callback(callback) {

    }

    void init() {
        _listen_socket.socket();
        _listen_socket.bind(_port);
        _listen_socket.listen();
        lg(INFO, "server initialized");
    }   

    void run() {
        signal(SIGCHLD, SIG_IGN);
        signal(SIGPIPE, SIG_IGN);
        lg(INFO, "server running");
        while(true) {
            // 接收客户端数据
            struct sockaddr_in client;
            int newfd = _listen_socket.accept(&client);
            if(newfd < 0) {
                continue;
            }
            // 子进程提供服务
            if(fork() == 0) {
                _listen_socket.close();
                string str_stream;
                while(true) {
                    char buffer[default_buffer_size];
                    size_t n = read(newfd, buffer, sizeof(buffer) - 1);
                    if(n <= 0) {
                        if(n < 0) {
                            lg(FATAL, "read error: %s", strerror(errno));
                        }
                        else {
                            lg(WARNING, "read end of file");
                        }
                        break;
                    }
                    lg(INFO, "server read success");
                    buffer[n] = '\0';
                    str_stream += buffer;
                    
                    // 发送回客户端
                    while(true) {
                        string packet = _callback(str_stream);
                        if(packet.empty()) {
                            break;
                        }
                        n = write(newfd, packet.c_str(), packet.size());
                        if(n <= 0) {
                            lg(FATAL, "write error: %s", strerror(errno));
                            goto there;
                        }
                        lg(INFO, "server write success");
                    }
                    cout << endl;
                }
                there:
                close(newfd);
                exit(0);
            }
            // 父进程
            close(newfd);
        }
    }
private:
    uint16_t _port;
    Socket _listen_socket;
    func_t _callback;
};